package com.taing.sample.web;

import cn.hutool.core.io.FileUtil;
import com.taing.sample.model.FullFileMode;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.taing.sample.web.SearchUitl.index_path;
import static com.taing.sample.web.SearchUitl.isEmptyIndexDir;
import static com.taing.sample.web.SearchUitl.source_path;


/**
 * @Author tianyi
 * @Description // todo
 * @Date 2024 - 12 - 29
 **/
public class CreateIndex {


    /**
     * 创建索引
     *
     * @throws IOException
     */
    public static void createIndex() throws Exception {
        //指定索引库存放的路径
        Directory directory = FSDirectory.open(new File(index_path).toPath());
        //索引库还可以存放到内存中
        //Directory directory = new RAMDirectory();
        //创建indexwriterCofig对象
        IndexWriterConfig config = new IndexWriterConfig();
        //创建indexwriter对象
        IndexWriter indexWriter = new IndexWriter(directory, config);

        File dir = new File(source_path);
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                continue;
            }


            // 文件路径
            String filePath = f.getPath();
            //文件名
            String fileName = f.getName();
            //文件内容
            String fileContent = FileUtil.readUtf8String(f);
            String md5Value = SearchUitl.extractCheckSum(filePath, "MD5");
            if (searchIndexByCode(md5Value)) {
                System.out.println("重复数据");
                continue;
            }
            //文件的大小
            long fileSize = FileUtil.size(f);
            //创建文件名域
            //第一个参数：域的名称
            //第二个参数：域的内容
            //第三个参数：是否存储
            Field fileNameField = new TextField(SearchUitl.FullFileField.filename.name(), fileName, Field.Store.YES);
            //文件路径域（不分析、不索引、只存储）
            Field filePathField = new TextField(SearchUitl.FullFileField.path.name(), filePath, Field.Store.YES);
            //文件大小域
            Field fileSizeField = new TextField(SearchUitl.FullFileField.size.name(), fileSize + "", Field.Store.YES);
            //文件唯一编号
            Field fileCode = new TextField(SearchUitl.FullFileField.filecode.name(), md5Value, Field.Store.YES);
            String[] segmentArray = fileContent.split("\n");
            for (String segment : segmentArray) {
                if (segment.trim().equals("")) {
                    continue;
                }
                //文件内容域
                Field fileContentField = new TextField(SearchUitl.FullFileField.content.name(), segment, Field.Store.YES);
                //创建document对象
                Document document = new Document();
                document.add(fileNameField);
                document.add(fileContentField);
                document.add(filePathField);
                document.add(fileSizeField);
                document.add(fileCode);
                //创建索引，并写入索引库
                indexWriter.addDocument(document);
            }

        }
        //关闭indexwriter
        indexWriter.close();
    }

    /**
     * 查询索引
     *
     * @throws IOException
     */
    public static boolean searchIndexByCode(String fileCode) throws IOException {
        if (isEmptyIndexDir(index_path)) {
            return false;
        }
        //指定索引库存放的路径
        Directory directory = FSDirectory.open(new File(index_path).toPath());
        //创建indexReader对象
        IndexReader indexReader = DirectoryReader.open(directory);
        //创建indexsearcher对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //创建查询
        Query query = new TermQuery(new Term("filecode", fileCode));
        System.out.println("====>" + fileCode);
        //执行查询
        //第一个参数是查询对象，第二个参数是查询结果返回的最大记录数
        TopDocs topDocs = indexSearcher.search(query, 10);
        //查询结果的总条数
        System.out.println("查询结果的总条数：" + topDocs.totalHits);
        //关闭indexreader对象
        indexReader.close();
        if (topDocs.totalHits.value > 0) {
            return true;
        }
        return false;
    }

    public static List<FullFileMode> fullTextSearch(FullFileMode fileMode) throws IOException, ParseException, InvalidTokenOffsetsException {
        Directory directory = FSDirectory.open(new File(index_path).toPath());
        //创建indexReader对象
        IndexReader indexReader = DirectoryReader.open(directory);
        //创建indexsearcher对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //创建查询
        //创建queryparser对象
        //第一个参数默认搜索的域
        //第二个参数就是分析器对象
        Analyzer ikAnalyzer = new IKAnalyzer();
        QueryParser queryParser = new QueryParser(SearchUitl.FullFileField.content.name(), ikAnalyzer);
        //要解析分词的内容
        Query query = queryParser.parse(fileMode.getFileContent());
        //打印query执行的查询语法
        System.out.println(query);

        // Query query = new TermQuery(new Term("content", fileMode.getFileContent()));
        System.out.println("====>" + fileMode.getFileContent());
        //执行查询
        //第一个参数是查询对象，第二个参数是查询结果返回的最大记录数
        TopDocs topDocs = indexSearcher.search(query, 10);
        //查询结果的总条数
        System.out.println("查询结果的总条数：" + topDocs.totalHits);
        QueryScorer queryScorer = new QueryScorer(query);
        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span> style='color:red'", "</span>");
        Highlighter highlighter = new Highlighter(simpleHTMLFormatter, queryScorer);
        List<FullFileMode> fullFileModeList = new ArrayList<>();
        if (topDocs.scoreDocs.length > 0) {
            for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
                //scoreDoc.doc属性就是document对象的id
                //根据document的id找到document对象
                Document document = indexSearcher.doc(scoreDoc.doc);
                FullFileMode fullFileMode = new FullFileMode();
                fullFileMode.setFileCode(document.get(SearchUitl.FullFileField.filecode.name()));
                fullFileMode.setFileName(document.get(SearchUitl.FullFileField.filename.name()));
                TokenStream tokenStream = ikAnalyzer.tokenStream(SearchUitl.FullFileField.content.name(), document.get(SearchUitl.FullFileField.content.name()));
                String fieldContent = highlighter.getBestFragment(tokenStream, document.get(SearchUitl.FullFileField.content.name()));
                fullFileMode.setFileContent(fieldContent);
                fullFileMode.setFileSize(document.get(SearchUitl.FullFileField.size.name()));
                fullFileMode.setFilePath(document.get(SearchUitl.FullFileField.path.name()));
                fullFileModeList.add(fullFileMode);
            }
        }
        //关闭indexreader对象
        indexReader.close();
        return fullFileModeList;
    }

    public static void main(String[] args) throws Exception {
        CreateIndex.createIndex();
        FullFileMode fullFileMode = new FullFileMode();
        fullFileMode.setFileContent("韩立心里很高兴");
        List<FullFileMode> fullFileModeList = CreateIndex.fullTextSearch(fullFileMode);
        for (FullFileMode fullFileMode1 : fullFileModeList) {
            System.out.println(fullFileMode1.getFileName());
            System.out.println(fullFileMode1.getFileCode());
            System.out.println(fullFileMode1.getFilePath());
            System.out.println(fullFileMode1.getFileContent());
        }
        String test = "，看不出原来的本来面目，还若有若无的散发着淡淡的霉味。\n" +
                "\n" +
                "    在他身边紧挨着的另一人，是二哥<span> style='color:red'韩</span>铸，酣睡的十分香甜，从他身上不时传来轻重不一的阵阵打呼声。\n" +
                "\n" +
                "    离床大约半丈远的地方";
        String[] test_array = test.split("\n");
        for (int i = 0; i < test_array.length; i++) {
            System.out.println(test_array[i]);

        }
    }
}
